1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module soup.Message; 26 27 private import gio.IOStream; 28 private import gio.TlsCertificate; 29 private import glib.ConstructionException; 30 private import glib.HashTable; 31 private import glib.Str; 32 private import gobject.ObjectG; 33 private import gobject.Signals; 34 private import soup.Address; 35 private import soup.Buffer; 36 private import soup.Request; 37 private import soup.URI; 38 private import soup.c.functions; 39 public import soup.c.types; 40 private import std.algorithm; 41 42 43 /** 44 * Represents an HTTP message being sent or received. 45 * 46 * @status_code will normally be a #SoupStatus value, eg, 47 * %SOUP_STATUS_OK, though of course it might actually be an unknown 48 * status code. @reason_phrase is the actual text returned from the 49 * server, which may or may not correspond to the "standard" 50 * description of @status_code. At any rate, it is almost certainly 51 * not localized, and not very descriptive even if it is in the user's 52 * language; you should not use @reason_phrase in user-visible 53 * messages. Rather, you should look at @status_code, and determine an 54 * end-user-appropriate message based on that and on what you were 55 * trying to do. 56 * 57 * As described in the #SoupMessageBody documentation, the 58 * @request_body and @response_body <literal>data</literal> fields 59 * will not necessarily be filled in at all times. When the body 60 * fields are filled in, they will be terminated with a '\0' byte 61 * (which is not included in the <literal>length</literal>), so you 62 * can use them as ordinary C strings (assuming that you know that the 63 * body doesn't have any other '\0' bytes). 64 * 65 * For a client-side #SoupMessage, @request_body's 66 * <literal>data</literal> is usually filled in right before libsoup 67 * writes the request to the network, but you should not count on 68 * this; use soup_message_body_flatten() if you want to ensure that 69 * <literal>data</literal> is filled in. If you are not using 70 * #SoupRequest to read the response, then @response_body's 71 * <literal>data</literal> will be filled in before 72 * #SoupMessage::finished is emitted. (If you are using #SoupRequest, 73 * then the message body is not accumulated by default, so 74 * @response_body's <literal>data</literal> will always be %NULL.) 75 * 76 * For a server-side #SoupMessage, @request_body's %data will be 77 * filled in before #SoupMessage::got_body is emitted. 78 * 79 * To prevent the %data field from being filled in at all (eg, if you 80 * are handling the data from a #SoupMessage::got_chunk, and so don't 81 * need to see it all at the end), call 82 * soup_message_body_set_accumulate() on @response_body or 83 * @request_body as appropriate, passing %FALSE. 84 */ 85 public class Message : ObjectG 86 { 87 /** the main Gtk struct */ 88 protected SoupMessage* soupMessage; 89 90 /** Get the main Gtk struct */ 91 public SoupMessage* getMessageStruct(bool transferOwnership = false) 92 { 93 if (transferOwnership) 94 ownedRef = false; 95 return soupMessage; 96 } 97 98 /** the main Gtk struct as a void* */ 99 protected override void* getStruct() 100 { 101 return cast(void*)soupMessage; 102 } 103 104 /** 105 * Sets our main struct and passes it to the parent class. 106 */ 107 public this (SoupMessage* soupMessage, bool ownedRef = false) 108 { 109 this.soupMessage = soupMessage; 110 super(cast(GObject*)soupMessage, ownedRef); 111 } 112 113 114 /** */ 115 public static GType getType() 116 { 117 return soup_message_get_type(); 118 } 119 120 /** 121 * Creates a new empty #SoupMessage, which will connect to @uri 122 * 123 * Params: 124 * method = the HTTP method for the created request 125 * uriString = the destination endpoint (as a string) 126 * 127 * Returns: the new #SoupMessage (or %NULL if @uri 128 * could not be parsed). 129 * 130 * Throws: ConstructionException GTK+ fails to create the object. 131 */ 132 public this(string method, string uriString) 133 { 134 auto __p = soup_message_new(Str.toStringz(method), Str.toStringz(uriString)); 135 136 if(__p is null) 137 { 138 throw new ConstructionException("null returned by new"); 139 } 140 141 this(cast(SoupMessage*) __p, true); 142 } 143 144 /** 145 * Creates a new empty #SoupMessage, which will connect to @uri 146 * 147 * Params: 148 * method = the HTTP method for the created request 149 * uri = the destination endpoint (as a #SoupURI) 150 * 151 * Returns: the new #SoupMessage 152 * 153 * Throws: ConstructionException GTK+ fails to create the object. 154 */ 155 public this(string method, URI uri) 156 { 157 auto __p = soup_message_new_from_uri(Str.toStringz(method), (uri is null) ? null : uri.getURIStruct()); 158 159 if(__p is null) 160 { 161 throw new ConstructionException("null returned by new_from_uri"); 162 } 163 164 this(cast(SoupMessage*) __p, true); 165 } 166 167 /** 168 * Adds a signal handler to @msg for @signal, as with 169 * g_signal_connect(), but the @callback will only be run if @msg's 170 * incoming messages headers (that is, the 171 * <literal>request_headers</literal> for a client #SoupMessage, or 172 * the <literal>response_headers</literal> for a server #SoupMessage) 173 * contain a header named @header. 174 * 175 * Params: 176 * signal = signal to connect the handler to. 177 * header = HTTP response header to match against 178 * callback = the header handler 179 * userData = data to pass to @handler_cb 180 * 181 * Returns: the handler ID from g_signal_connect() 182 */ 183 public uint addHeaderHandler(string signal, string header, GCallback callback, void* userData) 184 { 185 return soup_message_add_header_handler(soupMessage, Str.toStringz(signal), Str.toStringz(header), callback, userData); 186 } 187 188 /** 189 * Adds a signal handler to @msg for @signal, as with 190 * g_signal_connect(), but the @callback will only be run if @msg has 191 * the status @status_code. 192 * 193 * @signal must be a signal that will be emitted after @msg's status 194 * is set. For a client #SoupMessage, this means it can't be a "wrote" 195 * signal. For a server #SoupMessage, this means it can't be a "got" 196 * signal. 197 * 198 * Params: 199 * signal = signal to connect the handler to. 200 * statusCode = status code to match against 201 * callback = the header handler 202 * userData = data to pass to @handler_cb 203 * 204 * Returns: the handler ID from g_signal_connect() 205 */ 206 public uint addStatusCodeHandler(string signal, uint statusCode, GCallback callback, void* userData) 207 { 208 return soup_message_add_status_code_handler(soupMessage, Str.toStringz(signal), statusCode, callback, userData); 209 } 210 211 /** */ 212 public void contentSniffed(string contentType, HashTable params) 213 { 214 soup_message_content_sniffed(soupMessage, Str.toStringz(contentType), (params is null) ? null : params.getHashTableStruct()); 215 } 216 217 /** 218 * This disables the actions of #SoupSessionFeature<!-- -->s with the 219 * given @feature_type (or a subclass of that type) on @msg, so that 220 * @msg is processed as though the feature(s) hadn't been added to the 221 * session. Eg, passing #SOUP_TYPE_CONTENT_SNIFFER for @feature_type 222 * will disable Content-Type sniffing on the message. 223 * 224 * You must call this before queueing @msg on a session; calling it on 225 * a message that has already been queued is undefined. In particular, 226 * you cannot call this on a message that is being requeued after a 227 * redirect or authentication. 228 * 229 * Params: 230 * featureType = the #GType of a #SoupSessionFeature 231 * 232 * Since: 2.28 233 */ 234 public void disableFeature(GType featureType) 235 { 236 soup_message_disable_feature(soupMessage, featureType); 237 } 238 239 /** */ 240 public void finished() 241 { 242 soup_message_finished(soupMessage); 243 } 244 245 /** 246 * Gets the address @msg's URI points to. After first setting the 247 * URI on a message, this will be unresolved, although the message's 248 * session will resolve it before sending the message. 249 * 250 * Returns: the address @msg's URI points to 251 * 252 * Since: 2.26 253 */ 254 public Address getAddress() 255 { 256 auto __p = soup_message_get_address(soupMessage); 257 258 if(__p is null) 259 { 260 return null; 261 } 262 263 return ObjectG.getDObject!(Address)(cast(SoupAddress*) __p); 264 } 265 266 /** 267 * Gets @msg's first-party #SoupURI 268 * 269 * Returns: the @msg's first party #SoupURI 270 * 271 * Since: 2.30 272 */ 273 public URI getFirstParty() 274 { 275 auto __p = soup_message_get_first_party(soupMessage); 276 277 if(__p is null) 278 { 279 return null; 280 } 281 282 return ObjectG.getDObject!(URI)(cast(SoupURI*) __p); 283 } 284 285 /** 286 * Gets the flags on @msg 287 * 288 * Returns: the flags 289 */ 290 public SoupMessageFlags getFlags() 291 { 292 return soup_message_get_flags(soupMessage); 293 } 294 295 /** 296 * Gets the HTTP version of @msg. This is the minimum of the 297 * version from the request and the version from the response. 298 * 299 * Returns: the HTTP version 300 */ 301 public SoupHTTPVersion getHttpVersion() 302 { 303 return soup_message_get_http_version(soupMessage); 304 } 305 306 /** 307 * If @msg is using https (or attempted to use https but got 308 * %SOUP_STATUS_SSL_FAILED), this retrieves the #GTlsCertificate 309 * associated with its connection, and the #GTlsCertificateFlags 310 * showing what problems, if any, have been found with that 311 * certificate. 312 * 313 * <note><para>This is only meaningful with messages processed by a #SoupSession and is 314 * not useful for messages received by a #SoupServer</para></note> 315 * 316 * Params: 317 * certificate = @msg's TLS certificate 318 * errors = the verification status of @certificate 319 * 320 * Returns: %TRUE if @msg used/attempted https, %FALSE if not 321 * 322 * Since: 2.34 323 */ 324 public bool getHttpsStatus(out TlsCertificate certificate, out GTlsCertificateFlags errors) 325 { 326 GTlsCertificate* outcertificate = null; 327 328 auto __p = soup_message_get_https_status(soupMessage, &outcertificate, &errors) != 0; 329 330 certificate = ObjectG.getDObject!(TlsCertificate)(outcertificate); 331 332 return __p; 333 } 334 335 /** */ 336 public bool getIsTopLevelNavigation() 337 { 338 return soup_message_get_is_top_level_navigation(soupMessage) != 0; 339 } 340 341 /** 342 * Retrieves the #SoupMessagePriority. If not set this value defaults 343 * to #SOUP_MESSAGE_PRIORITY_NORMAL. 344 * 345 * Returns: the priority of the message. 346 * 347 * Since: 2.44 348 */ 349 public SoupMessagePriority getPriority() 350 { 351 return soup_message_get_priority(soupMessage); 352 } 353 354 /** 355 * Gets @msg's site for cookies #SoupURI 356 * 357 * Returns: the @msg's site for cookies #SoupURI 358 * 359 * Since: 2.70 360 */ 361 public URI getSiteForCookies() 362 { 363 auto __p = soup_message_get_site_for_cookies(soupMessage); 364 365 if(__p is null) 366 { 367 return null; 368 } 369 370 return ObjectG.getDObject!(URI)(cast(SoupURI*) __p); 371 } 372 373 /** 374 * If @msg is associated with a #SoupRequest, this returns that 375 * request. Otherwise it returns %NULL. 376 * 377 * Returns: @msg's associated #SoupRequest 378 * 379 * Since: 2.42 380 */ 381 public Request getSoupRequest() 382 { 383 auto __p = soup_message_get_soup_request(soupMessage); 384 385 if(__p is null) 386 { 387 return null; 388 } 389 390 return ObjectG.getDObject!(Request)(cast(SoupRequest*) __p); 391 } 392 393 /** 394 * Gets @msg's URI 395 * 396 * Returns: the URI @msg is targeted for. 397 */ 398 public URI getUri() 399 { 400 auto __p = soup_message_get_uri(soupMessage); 401 402 if(__p is null) 403 { 404 return null; 405 } 406 407 return ObjectG.getDObject!(URI)(cast(SoupURI*) __p); 408 } 409 410 /** */ 411 public void gotBody() 412 { 413 soup_message_got_body(soupMessage); 414 } 415 416 /** */ 417 public void gotChunk(Buffer chunk) 418 { 419 soup_message_got_chunk(soupMessage, (chunk is null) ? null : chunk.getBufferStruct()); 420 } 421 422 /** */ 423 public void gotHeaders() 424 { 425 soup_message_got_headers(soupMessage); 426 } 427 428 /** */ 429 public void gotInformational() 430 { 431 soup_message_got_informational(soupMessage); 432 } 433 434 /** 435 * Get whether #SoupSessionFeature<!-- -->s of the given @feature_type 436 * (or a subclass of that type) are disabled on @msg. 437 * See soup_message_disable_feature(). 438 * 439 * Params: 440 * featureType = the #GType of a #SoupSessionFeature 441 * 442 * Returns: %TRUE if feature is disabled, or %FALSE otherwise. 443 * 444 * Since: 2.72 445 */ 446 public bool isFeatureDisabled(GType featureType) 447 { 448 return soup_message_is_feature_disabled(soupMessage, featureType) != 0; 449 } 450 451 /** 452 * Determines whether or not @msg's connection can be kept alive for 453 * further requests after processing @msg, based on the HTTP version, 454 * Connection header, etc. 455 * 456 * Returns: %TRUE or %FALSE. 457 */ 458 public bool isKeepalive() 459 { 460 return soup_message_is_keepalive(soupMessage) != 0; 461 } 462 463 /** */ 464 public void restarted() 465 { 466 soup_message_restarted(soupMessage); 467 } 468 469 /** 470 * Sets an alternate chunk-allocation function to use when reading 471 * @msg's body when using the traditional (ie, 472 * non-#SoupRequest<!-- -->-based) API. Every time data is available 473 * to read, libsoup will call @allocator, which should return a 474 * #SoupBuffer. (See #SoupChunkAllocator for additional details.) 475 * Libsoup will then read data from the network into that buffer, and 476 * update the buffer's <literal>length</literal> to indicate how much 477 * data it read. 478 * 479 * Generally, a custom chunk allocator would be used in conjunction 480 * with soup_message_body_set_accumulate() %FALSE and 481 * #SoupMessage::got_chunk, as part of a strategy to avoid unnecessary 482 * copying of data. However, you cannot assume that every call to the 483 * allocator will be followed by a call to your 484 * #SoupMessage::got_chunk handler; if an I/O error occurs, then the 485 * buffer will be unreffed without ever having been used. If your 486 * buffer-allocation strategy requires special cleanup, use 487 * soup_buffer_new_with_owner() rather than doing the cleanup from the 488 * #SoupMessage::got_chunk handler. 489 * 490 * The other thing to remember when using non-accumulating message 491 * bodies is that the buffer passed to the #SoupMessage::got_chunk 492 * handler will be unreffed after the handler returns, just as it 493 * would be in the non-custom-allocated case. If you want to hand the 494 * chunk data off to some other part of your program to use later, 495 * you'll need to ref the #SoupBuffer (or its owner, in the 496 * soup_buffer_new_with_owner() case) to ensure that the data remains 497 * valid. 498 * 499 * Deprecated: #SoupRequest provides a much simpler API that lets you 500 * read the response directly into your own buffers without needing to 501 * mess with callbacks, pausing/unpausing, etc. 502 * 503 * Params: 504 * allocator = the chunk allocator callback 505 * userData = data to pass to @allocator 506 * destroyNotify = destroy notifier to free @user_data when @msg is 507 * destroyed 508 */ 509 public void setChunkAllocator(SoupChunkAllocator allocator, void* userData, GDestroyNotify destroyNotify) 510 { 511 soup_message_set_chunk_allocator(soupMessage, allocator, userData, destroyNotify); 512 } 513 514 /** 515 * Sets @first_party as the main document #SoupURI for @msg. For 516 * details of when and how this is used refer to the documentation for 517 * #SoupCookieJarAcceptPolicy. 518 * 519 * Params: 520 * firstParty = the #SoupURI for the @msg's first party 521 * 522 * Since: 2.30 523 */ 524 public void setFirstParty(URI firstParty) 525 { 526 soup_message_set_first_party(soupMessage, (firstParty is null) ? null : firstParty.getURIStruct()); 527 } 528 529 /** 530 * Sets the specified flags on @msg. 531 * 532 * Params: 533 * flags = a set of #SoupMessageFlags values 534 */ 535 public void setFlags(SoupMessageFlags flags) 536 { 537 soup_message_set_flags(soupMessage, flags); 538 } 539 540 /** 541 * Sets the HTTP version on @msg. The default version is 542 * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain 543 * functionality from being used. 544 * 545 * Params: 546 * version_ = the HTTP version 547 */ 548 public void setHttpVersion(SoupHTTPVersion version_) 549 { 550 soup_message_set_http_version(soupMessage, version_); 551 } 552 553 /** 554 * See the [same-site spec](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00) 555 * for more information. 556 * 557 * Params: 558 * isTopLevelNavigation = if %TRUE indicate the current request is a top-level navigation 559 * 560 * Since: 2.70 561 */ 562 public void setIsTopLevelNavigation(bool isTopLevelNavigation) 563 { 564 soup_message_set_is_top_level_navigation(soupMessage, isTopLevelNavigation); 565 } 566 567 /** 568 * Sets the priority of a message. Note that this won't have any 569 * effect unless used before the message is added to the session's 570 * message processing queue. 571 * 572 * The message will be placed just before any other previously added 573 * message with lower priority (messages with the same priority are 574 * processed on a FIFO basis). 575 * 576 * Setting priorities does not currently work with #SoupSessionSync 577 * (or with synchronous messages on a plain #SoupSession) because in 578 * the synchronous/blocking case, priority ends up being determined 579 * semi-randomly by thread scheduling. 580 * 581 * Params: 582 * priority = the #SoupMessagePriority 583 * 584 * Since: 2.44 585 */ 586 public void setPriority(SoupMessagePriority priority) 587 { 588 soup_message_set_priority(soupMessage, priority); 589 } 590 591 /** 592 * Sets @msg's status_code to @status_code and adds a Location header 593 * pointing to @redirect_uri. Use this from a #SoupServer when you 594 * want to redirect the client to another URI. 595 * 596 * @redirect_uri can be a relative URI, in which case it is 597 * interpreted relative to @msg's current URI. In particular, if 598 * @redirect_uri is just a path, it will replace the path 599 * <emphasis>and query</emphasis> of @msg's URI. 600 * 601 * Params: 602 * statusCode = a 3xx status code 603 * redirectUri = the URI to redirect @msg to 604 * 605 * Since: 2.38 606 */ 607 public void setRedirect(uint statusCode, string redirectUri) 608 { 609 soup_message_set_redirect(soupMessage, statusCode, Str.toStringz(redirectUri)); 610 } 611 612 /** 613 * Convenience function to set the request body of a #SoupMessage. If 614 * @content_type is %NULL, the request body must be empty as well. 615 * 616 * Params: 617 * contentType = MIME Content-Type of the body 618 * reqUse = a #SoupMemoryUse describing how to handle @req_body 619 * reqBody = a data buffer containing the body of the message request. 620 */ 621 public void setRequest(string contentType, SoupMemoryUse reqUse, string reqBody) 622 { 623 soup_message_set_request(soupMessage, Str.toStringz(contentType), reqUse, Str.toStringz(reqBody), cast(size_t)reqBody.length); 624 } 625 626 /** 627 * Convenience function to set the response body of a #SoupMessage. If 628 * @content_type is %NULL, the response body must be empty as well. 629 * 630 * Params: 631 * contentType = MIME Content-Type of the body 632 * respUse = a #SoupMemoryUse describing how to handle @resp_body 633 * respBody = a data buffer containing the body of the message response. 634 */ 635 public void setResponse(string contentType, SoupMemoryUse respUse, string respBody) 636 { 637 soup_message_set_response(soupMessage, Str.toStringz(contentType), respUse, Str.toStringz(respBody), cast(size_t)respBody.length); 638 } 639 640 /** 641 * Sets @site_for_cookies as the policy URL for same-site cookies for @msg. 642 * 643 * It is either the URL of the top-level document or %NULL depending on whether the registrable 644 * domain of this document's URL matches the registrable domain of its parent's/opener's 645 * URL. For the top-level document it is set to the document's URL. 646 * 647 * See the [same-site spec](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00) 648 * for more information. 649 * 650 * Params: 651 * siteForCookies = the #SoupURI for the @msg's site for cookies 652 * 653 * Since: 2.70 654 */ 655 public void setSiteForCookies(URI siteForCookies) 656 { 657 soup_message_set_site_for_cookies(soupMessage, (siteForCookies is null) ? null : siteForCookies.getURIStruct()); 658 } 659 660 /** 661 * Sets @msg's status code to @status_code. If @status_code is a 662 * known value, it will also set @msg's reason_phrase. 663 * 664 * Params: 665 * statusCode = an HTTP status code 666 */ 667 public void setStatus(uint statusCode) 668 { 669 soup_message_set_status(soupMessage, statusCode); 670 } 671 672 /** 673 * Sets @msg's status code and reason phrase. 674 * 675 * Params: 676 * statusCode = an HTTP status code 677 * reasonPhrase = a description of the status 678 */ 679 public void setStatusFull(uint statusCode, string reasonPhrase) 680 { 681 soup_message_set_status_full(soupMessage, statusCode, Str.toStringz(reasonPhrase)); 682 } 683 684 /** 685 * Sets @msg's URI to @uri. If @msg has already been sent and you want 686 * to re-send it with the new URI, you need to call 687 * soup_session_requeue_message(). 688 * 689 * Params: 690 * uri = the new #SoupURI 691 */ 692 public void setUri(URI uri) 693 { 694 soup_message_set_uri(soupMessage, (uri is null) ? null : uri.getURIStruct()); 695 } 696 697 /** */ 698 public void starting() 699 { 700 soup_message_starting(soupMessage); 701 } 702 703 /** */ 704 public void wroteBody() 705 { 706 soup_message_wrote_body(soupMessage); 707 } 708 709 /** */ 710 public void wroteBodyData(Buffer chunk) 711 { 712 soup_message_wrote_body_data(soupMessage, (chunk is null) ? null : chunk.getBufferStruct()); 713 } 714 715 /** */ 716 public void wroteChunk() 717 { 718 soup_message_wrote_chunk(soupMessage); 719 } 720 721 /** */ 722 public void wroteHeaders() 723 { 724 soup_message_wrote_headers(soupMessage); 725 } 726 727 /** */ 728 public void wroteInformational() 729 { 730 soup_message_wrote_informational(soupMessage); 731 } 732 733 /** 734 * This signal is emitted after #SoupMessage::got-headers, and 735 * before the first #SoupMessage::got-chunk. If content 736 * sniffing is disabled, or no content sniffing will be 737 * performed, due to the sniffer deciding to trust the 738 * Content-Type sent by the server, this signal is emitted 739 * immediately after #SoupMessage::got-headers, and @type is 740 * %NULL. 741 * 742 * If the #SoupContentSniffer feature is enabled, and the 743 * sniffer decided to perform sniffing, the first 744 * #SoupMessage::got-chunk emission may be delayed, so that the 745 * sniffer has enough data to correctly sniff the content. It 746 * notified the library user that the content has been 747 * sniffed, and allows it to change the header contents in the 748 * message, if desired. 749 * 750 * After this signal is emitted, the data that was spooled so 751 * that sniffing could be done is delivered on the first 752 * emission of #SoupMessage::got-chunk. 753 * 754 * Params: 755 * type = the content type that we got from sniffing 756 * params = a #GHashTable with the parameters 757 * 758 * Since: 2.28 759 */ 760 gulong addOnContentSniffed(void delegate(string, HashTable, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 761 { 762 return Signals.connect(this, "content-sniffed", dlg, connectFlags ^ ConnectFlags.SWAPPED); 763 } 764 765 /** 766 * Emitted when all HTTP processing is finished for a message. 767 * (After #SoupMessage::got_body for client-side messages, or 768 * after #SoupMessage::wrote_body for server-side messages.) 769 */ 770 gulong addOnFinished(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 771 { 772 return Signals.connect(this, "finished", dlg, connectFlags ^ ConnectFlags.SWAPPED); 773 } 774 775 /** 776 * Emitted after receiving the complete message body. (For a 777 * server-side message, this means it has received the request 778 * body. For a client-side message, this means it has received 779 * the response body and is nearly done with the message.) 780 * 781 * See also soup_message_add_header_handler() and 782 * soup_message_add_status_code_handler(), which can be used 783 * to connect to a subset of emissions of this signal. 784 */ 785 gulong addOnGotBody(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 786 { 787 return Signals.connect(this, "got-body", dlg, connectFlags ^ ConnectFlags.SWAPPED); 788 } 789 790 /** 791 * Emitted after receiving a chunk of a message body. Note 792 * that "chunk" in this context means any subpiece of the 793 * body, not necessarily the specific HTTP 1.1 chunks sent by 794 * the other side. 795 * 796 * If you cancel or requeue @msg while processing this signal, 797 * then the current HTTP I/O will be stopped after this signal 798 * emission finished, and @msg's connection will be closed. 799 * 800 * Params: 801 * chunk = the just-read chunk 802 */ 803 gulong addOnGotChunk(void delegate(Buffer, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 804 { 805 return Signals.connect(this, "got-chunk", dlg, connectFlags ^ ConnectFlags.SWAPPED); 806 } 807 808 /** 809 * Emitted after receiving all message headers for a message. 810 * (For a client-side message, this is after receiving the 811 * Status-Line and response headers; for a server-side 812 * message, it is after receiving the Request-Line and request 813 * headers.) 814 * 815 * See also soup_message_add_header_handler() and 816 * soup_message_add_status_code_handler(), which can be used 817 * to connect to a subset of emissions of this signal. 818 * 819 * If you cancel or requeue @msg while processing this signal, 820 * then the current HTTP I/O will be stopped after this signal 821 * emission finished, and @msg's connection will be closed. 822 * (If you need to requeue a message--eg, after handling 823 * authentication or redirection--it is usually better to 824 * requeue it from a #SoupMessage::got_body handler rather 825 * than a #SoupMessage::got_headers handler, so that the 826 * existing HTTP connection can be reused.) 827 */ 828 gulong addOnGotHeaders(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 829 { 830 return Signals.connect(this, "got-headers", dlg, connectFlags ^ ConnectFlags.SWAPPED); 831 } 832 833 /** 834 * Emitted after receiving a 1xx (Informational) response for 835 * a (client-side) message. The response_headers will be 836 * filled in with the headers associated with the 837 * informational response; however, those header values will 838 * be erased after this signal is done. 839 * 840 * If you cancel or requeue @msg while processing this signal, 841 * then the current HTTP I/O will be stopped after this signal 842 * emission finished, and @msg's connection will be closed. 843 */ 844 gulong addOnGotInformational(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 845 { 846 return Signals.connect(this, "got-informational", dlg, connectFlags ^ ConnectFlags.SWAPPED); 847 } 848 849 /** 850 * Emitted to indicate that some network-related event 851 * related to @msg has occurred. This essentially proxies the 852 * #GSocketClient::event signal, but only for events that 853 * occur while @msg "owns" the connection; if @msg is sent on 854 * an existing persistent connection, then this signal will 855 * not be emitted. (If you want to force the message to be 856 * sent on a new connection, set the 857 * %SOUP_MESSAGE_NEW_CONNECTION flag on it.) 858 * 859 * See #GSocketClient::event for more information on what 860 * the different values of @event correspond to, and what 861 * @connection will be in each case. 862 * 863 * Params: 864 * event = the network event 865 * connection = the current state of the network connection 866 * 867 * Since: 2.38 868 */ 869 gulong addOnNetwork(void delegate(GSocketClientEvent, IOStream, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 870 { 871 return Signals.connect(this, "network-event", dlg, connectFlags ^ ConnectFlags.SWAPPED); 872 } 873 874 /** 875 * Emitted when a request that was already sent once is now 876 * being sent again (eg, because the first attempt received a 877 * redirection response, or because we needed to use 878 * authentication). 879 */ 880 gulong addOnRestarted(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 881 { 882 return Signals.connect(this, "restarted", dlg, connectFlags ^ ConnectFlags.SWAPPED); 883 } 884 885 /** 886 * Emitted just before a message is sent. 887 * 888 * Since: 2.50 889 */ 890 gulong addOnStarting(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 891 { 892 return Signals.connect(this, "starting", dlg, connectFlags ^ ConnectFlags.SWAPPED); 893 } 894 895 /** 896 * Emitted immediately after writing the complete body for a 897 * message. (For a client-side message, this means that 898 * libsoup is done writing and is now waiting for the response 899 * from the server. For a server-side message, this means that 900 * libsoup has finished writing the response and is nearly 901 * done with the message.) 902 */ 903 gulong addOnWroteBody(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 904 { 905 return Signals.connect(this, "wrote-body", dlg, connectFlags ^ ConnectFlags.SWAPPED); 906 } 907 908 /** 909 * Emitted immediately after writing a portion of the message 910 * body to the network. 911 * 912 * Unlike #SoupMessage::wrote_chunk, this is emitted after 913 * every successful write() call, not only after finishing a 914 * complete "chunk". 915 * 916 * Params: 917 * chunk = the data written 918 * 919 * Since: 2.24 920 */ 921 gulong addOnWroteBodyData(void delegate(Buffer, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 922 { 923 return Signals.connect(this, "wrote-body-data", dlg, connectFlags ^ ConnectFlags.SWAPPED); 924 } 925 926 /** 927 * Emitted immediately after writing a body chunk for a message. 928 * 929 * Note that this signal is not parallel to 930 * #SoupMessage::got_chunk; it is emitted only when a complete 931 * chunk (added with soup_message_body_append() or 932 * soup_message_body_append_buffer()) has been written. To get 933 * more useful continuous progress information, use 934 * #SoupMessage::wrote_body_data. 935 */ 936 gulong addOnWroteChunk(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 937 { 938 return Signals.connect(this, "wrote-chunk", dlg, connectFlags ^ ConnectFlags.SWAPPED); 939 } 940 941 /** 942 * Emitted immediately after writing the headers for a 943 * message. (For a client-side message, this is after writing 944 * the request headers; for a server-side message, it is after 945 * writing the response headers.) 946 */ 947 gulong addOnWroteHeaders(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 948 { 949 return Signals.connect(this, "wrote-headers", dlg, connectFlags ^ ConnectFlags.SWAPPED); 950 } 951 952 /** 953 * Emitted immediately after writing a 1xx (Informational) 954 * response for a (server-side) message. 955 */ 956 gulong addOnWroteInformational(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 957 { 958 return Signals.connect(this, "wrote-informational", dlg, connectFlags ^ ConnectFlags.SWAPPED); 959 } 960 }